package me.yricky.kaguya.base.lu

import me.yricky.kaguya.base.Reg
import me.yricky.kaguya.base.Signal

/**
 * 描述在特定条件下触发的组合逻辑块，对应Verilog中触发条件是信号变化的always
 */
class CombUnit(
    val logicBlocks:List<AssignBlock>
): LogicUnit(){

    override val inputSignals: List<Signal> = logicBlocks.flatMap { it.cases.map { it.from }.plus(it.default) }
    override val outputSignals: List<Reg> = logicBlocks.map { it.target }
}

/**
 * 描述在特定条件下触发的时序逻辑块，对应Verilog中边沿触发的always
 */
class SeqUnit(
    val trigCases:List<TrigCase>,
    val assignBlocks:List<AssignBlock>
): LogicUnit(){
    sealed class TrigCase(val signal: Signal)
    class NegEdge(signal: Signal): TrigCase(signal){
        init { assert(signal.width == 1) }
    }

    class PosEdge(signal: Signal): TrigCase(signal){
        init { assert(signal.width == 1) }
    }



    override val inputSignals: List<Signal> = trigCases.map { it.signal }
    override val outputSignals: List<Reg> = assignBlocks.map { it.target }
}

/**
 * 组合或时序逻辑块内，对一个寄存器进行赋值的逻辑抽象。
 * 当逻辑块被触发时，将[cases]中满足条件的信号赋值给[target]，若[cases]中的条件都不满足，则将[default]赋值给[target]
 */
class AssignBlock(
    val target: Reg,
    val cases:List<CaseFrom>,
    val default: Signal
)

/**
 * 表示[AssignBlock]中的一个赋值条件，[case]为真时条件满足，此时取值[from]
 */
class CaseFrom(
    val case: Signal,
    val from: Signal
){
    init {
        assert(case.width == 1)
    }
}

